#ifndef _SMOOTHNESS_H_
#define _SMOOTHNESS_H_

struct Smoothness
{
public:

    const char* getName()
    {
        const static char name[] = "Smoothness"; 
        return name;
    }
    
    template
    <
        typename SignalSystem
    >
    double operator()(SignalSystem& system)
    {
        using namespace std;
       
        double sum = 0;
        double peak = 0;
        
        for (int i = 0; i < system.size() ; ++i)
        {
            vector<double> rslt(system[i].size(), 0);
            vector<complex<double>> difference(rslt.size());
            
            adjacent_difference(
                    system[i].begin(), system[i].end(),
                    difference.begin()
            );
            
            difference[0] = 0;
            
            transform(
                difference.begin(), difference.end(),
                rslt.begin(),
                absolute<complex<double>,double>()
            );
        
            peak = max(peak, *max_element(rslt.begin(), rslt.end()));
            
            std::binder2nd
            <
                power<int, double>
            >
            power2(
                power<int, double>(),
                2
            );
            
            
            transform(
                rslt.begin(), rslt.end(),
                rslt.begin(),
                power2);
                
            sum =
                accumulate(
                    rslt.begin(), rslt.end(),
                    sum
                );
        }
        
        
        double avr = sqrt(sum / (system.size() * system[0].size()));
        //if (peak < avr)
        //    cout << "*****************" << endl << peak << " . " << avr << endl;
        return 1.0 - exp(1.0 - peak / avr);
    }
};

#endif // _PICK_FACTOR_H_
